//package com.eastfair.security.encrypt;
//
//import java.io.BufferedReader;
//import java.io.IOException;
//import java.io.PrintWriter;
//import java.nio.charset.StandardCharsets;
//import java.util.Arrays;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
//import javax.servlet.*;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//import com.alibaba.fastjson.JSONArray;
//import com.eastfair.core.encrypt.AesEncryptUtil;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.google.common.collect.Lists;
//
//import cn.hutool.core.util.StrUtil;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//
///***
// * Description 请求参数加密过滤器
// *
// * @date 16:34 2022/3/29
// */
//@Component
//@Slf4j
//public class ParamResultFilter implements Filter {
//
//    /**
//     * 参数是否加密
//     */
//    @Value("${emmp.aesencrypt.paramEncryptAble:false}")
//    private Boolean paramEncryptAble;
//
//    /**
//     * 结果是否加密
//     */
//    @Value("${emmp.aesencrypt.resultEncryptAble:false}")
//    private Boolean resultEncryptAble;
//
//    /**
//     * 排除加密解密的接口
//     */
//    @Value("${emmp.aesencrypt.excludeUrl:}")
//    private String[] excludeUrls;
//
//    /**
//     * 使用AES-128-CBC加密模式，key需要为16位,key和iv可以相同！
//     */
//    @Value("${emmp.aesencrypt.key:}")
//    private String key;
//
//    @Value("${emmp.aesencrypt.iv:}")
//    private String iv;
//
//    @Value("${emmp.aesencrypt.padding:}")
//    private String padding;
//
//    private List<String> excludes;
//
//    /**
//     * GET 请求方式
//     */
//    private static final String GET_REQUEST = "GET";
//
//    /**
//     * GET 请求方式
//     */
//    private static final String OPTIONS = "OPTIONS";
//
//    /**
//     * DELETE 请求方式
//     */
//    private static final String DELETE_REQUEST = "DELETE";
//
//    private static final String POST_REQUEST = "POST";
//
//    /**
//     * 加密字段
//     */
//    private static final String ENCRYPT_STR = "encryptStr";
//
//    /**
//     * 前端加密的请求,swagger 传输的时候没有这个请求头
//     */
//    private static final String ADVANCED = "Advanced";
//
//    @SneakyThrows
//    @Override
//    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
//        HttpServletRequest req = (HttpServletRequest)request;
//        String method = req.getMethod();
//        String requestUri = req.getRequestURI();
//        // 这里处理swagger 的过滤
//        boolean swaggerFlag = !StrUtil.isEmpty(requestUri) && requestUri.contains("/doc.html")
//                || requestUri.contains("/webjars/bycdao-ui/") || requestUri.contains("/swagger")
//                || requestUri.contains("/v2/");
//
//        if (DELETE_REQUEST.equals(method) || OPTIONS.equals(method) || swaggerFlag) {
//            // 这里是过滤器注册转发
//            chain.doFilter(request, response);
//            return;
//        }
//
//        // 允许跳过的接口
//        if (handleExcludeUrl(req)) {
//            // 这里是过滤器注册转发
//            chain.doFilter(request, response);
//            return;
//        }
//        // 是否参数加密
//        RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest)request);
//        // 前端加密之后的请求头
//        String product = req.getHeader("Product");
//        // 处理智搜的GET加密请求
//        if (ADVANCED.equals(product) && GET_REQUEST.equals(method) && paramEncryptAble) {
//            this.dealGetRequestDecode(requestWrapper);
//        }
//        // 如果可以json化一般都是swagger请求就直接请求
//        boolean jsonFlag = false;
//        // 处理post请求
//        if (POST_REQUEST.equals(method)) {
//            StringBuilder str = new StringBuilder();
//            String line;
//            BufferedReader reader;
//            reader = requestWrapper.getReader();
//            while ((line = reader.readLine()) != null) {
//                str.append(line);
//            }
//            String json;
//            if (StrUtil.isNotEmpty(str.toString())) {
//                try {
//                    JSONObject object = JSON.parseObject(str.toString());
//                    json = object.toJSONString();
//                    requestWrapper.setBody(json.getBytes(StandardCharsets.UTF_8));
//                    // 能json 话说明是swagger的
//                    jsonFlag = true;
//                } catch (Exception e) {
//                    try {
//                        JSONArray object = JSON.parseArray(str.toString());
//                        json = object.toJSONString();
//                        requestWrapper.setBody(json.getBytes(StandardCharsets.UTF_8));
//                        // 能json 话说明是swagger的
//                        jsonFlag = true;
//                    } catch (Exception exception) {
//                        log.warn("不是常规的json字符串解密异常字符串:{},异常内容：{}", str.toString(), e.getMessage());
//                    }
//                }
//            }
//            // 如果不是swagger传过来的数据否则就对post进行解密且对返回的数据加密
//            if (!jsonFlag) {
//                // post请求内容需要解密
//                json = AesEncryptUtil.desEncrypt(str.toString(), key, iv, padding);
//                log.info("解密之后的字符串:{}", json);
//                requestWrapper.setBody(json.getBytes(StandardCharsets.UTF_8));
//            }
//        }
//        // 结果是否加密
//        if (resultEncryptAble && !jsonFlag) {
//            // 且对返回数据进行加密 ,此地方代码过于冗余后续可能需要对整个方法进行优化
//            this.encryptResultData(chain, response, requestWrapper);
//        } else {
//            chain.doFilter(requestWrapper, response);
//        }
//
//    }
//
//    /**
//     * @description: 加密返回数据
//     * @param: [chain,
//     *             response, requestWrapper]
//     * @return: void
//     * @date: 2022/4/12 18:16
//     */
//    public void encryptResultData(FilterChain chain, ServletResponse response, RequestWrapper requestWrapper) {
//        // 且对返回数据进行加密 ,此地方代码过于冗余后续可能需要对整个方法进行优化
//        try {
//            // 请注意响应处理 包装响应对象 res 并缓存响应数据,只有需要加密数据才使用这个 ResponseWrapper
//            ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse)response);
//            // 执行业务逻辑 交给下一个过滤器或servlet处理
//            // 这里是过滤器注册转发
//            chain.doFilter(requestWrapper, responseWrapper);
//            // 是否结果加密
//            byte[] resData = responseWrapper.getResponseData();
//            // 设置响应内容格式，防止解析响应内容时出错
//            // responseWrapper.setContentType("text/plain;charset=UTF-8");
//            // 加密响应报文并响应
//            String resultEncrypt = AesEncryptUtil.encrypt(new String(resData), key, iv, padding);
//            // 这里得用原始的流去处理返回 切记
//            PrintWriter out = response.getWriter();
//            out.print(resultEncrypt);
//            out.flush();
//            out.close();
//
//        } catch (Exception e) {
//            log.error("返回数据加密失败：{}", e.getMessage());
//            try {
//                getFailResponse((HttpServletResponse)response);
//            } catch (IOException ioException) {
//                log.error("io异常：{}", ioException.getMessage());
//            }
//
//        }
//    }
//
//    /**
//     * 前端get请求 加密之后需要解码请求参数
//     *
//     * @param requestWrapper
//     */
//    private void dealGetRequestDecode(RequestWrapper requestWrapper) {
//        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
//        Map<String, Object> paras = new HashMap<>();
//        // 这里get 请求加密的value
//        parameterMap.forEach((paramKey, encryptValue) -> {
//            for (String s : encryptValue) {
//                try {
//                    // 解密请求的
//                    String params = AesEncryptUtil.desEncrypt(s, key, iv, padding);
//                    JSONObject jsonObject = JSON.parseObject(params);
//                    jsonObject.forEach((name, value) -> {
//                        String[] vs = {value + ""};
//                        paras.put(name, vs);
//                    });
//                } catch (Exception e) {
//                    log.info("get请求解密异常：{}", e.getMessage());
//                }
//            }
//
//        });
//        requestWrapper.addAllParameters(paras);
//        log.info("paramsMap:{}", parameterMap);
//    }
//
//    private void getFailResponse(HttpServletResponse response) throws IOException {
//        response.setCharacterEncoding("UTF-8");
//        response.setContentType("application/json; charset=utf-8");
//        PrintWriter out = null;
//        out = response.getWriter();
//        // out.write("{\n" +
//        // " \"status\":"+ Constant.ENCRYPT_FAIL +",\n" +
//        // " \"message\": null,\n" +
//        // " \"data\": []\n" +
//        // "}");
//        // 加密后的错误消息
//        out.write("服务端加密异常");
//        out.flush();
//        out.close();
//    }
//
//    @Override
//    public void destroy() {}
//
//    @Override
//    public void init(FilterConfig filterConfig) {
//        excludes = Lists.newArrayList(Arrays.asList(excludeUrls));
//        /*String excludesTemp = filterConfig.getInitParameter("excludes");
//        if (!StrUtil.isEmpty(excludesTemp)) {
//            String[] url = excludesTemp.split(",");
//            excludes.addAll(Arrays.asList(url));
//        }*/
//    }
//
//    private boolean handleExcludeUrl(HttpServletRequest request) {
//        if (CollectionUtils.isEmpty(excludes)) {
//            return false;
//        }
//        String url = request.getServletPath();
//        for (String pattern : excludes) {
//            Pattern p = Pattern.compile("^" + pattern);
//            Matcher m = p.matcher(url);
//            if (m.find()) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    /*public static void main(String[] args) {
//        String str = "http://localhost:8094/onlinePreview?url=%s&fileName=filename.xx";
//        String str2 = "http://localhost:8094/onlinePreview?";
//        System.out.println(str.substring(str.indexOf("?") + 1));
//        System.out.println(str2.substring(str2.indexOf("?") + 1));
//    }*/
//}